<script lang="ts" setup>
import { CaptchRefreshIcon, CaptchaBtnCloseIcon, CaptchaLoadingIcon } from '@/components/Icon'
import { useClickCaptchaHandler } from './hooks/handler'
import { ClickCaptchaConf, defaultConf } from './meta/conf'
import { ClickCaptchaData } from './meta/data'
import { ClickCaptchaEvent, ClickCaptchaExpose } from './meta/event'


defineOptions({ name: 'ClickCaptcha' })

// 本地配置
const props = withDefaults(
  defineProps<{
    config?: ClickCaptchaConf
    events?: ClickCaptchaEvent
    data: ClickCaptchaData
    [x: string]: any
  }>(),
  {
    config: defaultConf,
    events: () => ({}) as ClickCaptchaEvent,
    data: () => ({}) as ClickCaptchaData
  }
)

// 本地数据
const { data, events, config } = props
const localData = reactive<ClickCaptchaData>({ ...toRaw(data) })
const localEvent = reactive<ClickCaptchaEvent>({ ...toRaw(events) })
const localConfig = reactive<ClickCaptchaConf>({ ...defaultConf(), ...toRaw(config) })

// 绑定处理事件
const handler = useClickCaptchaHandler(localData, localEvent, () => {
  localData.thumb = ''
  localData.image = ''
})

// 包裹样式
const wrapperStyles = computed(() => {
  const hPadding = localConfig.horizontalPadding || 0
  const vPadding = localConfig.verticalPadding || 0
  const width = (localConfig.width || 0) + hPadding * 2 + (localConfig.showTheme ? 2 : 0)

  return {
    width: width + 'px',
    paddingLeft: hPadding + 'px',
    paddingRight: hPadding + 'px',
    paddingTop: vPadding + 'px',
    paddingBottom: vPadding + 'px'
  }
})

// 缩略图样式
const thumbStyles = computed(() => {
  return {
    width: localConfig.thumbWidth + 'px',
    height: localConfig.thumbHeight + 'px'
  }
})

// 样式
const imageStyles = computed(() => {
  return {
    width: localConfig.width + 'px',
    height: localConfig.height + 'px'
  }
})

// 图片显示状态
const hasDisplayImageState = computed(() => {
  return localData.image != '' || localData.thumb != ''
})

// 显示图片状态
const hasDisplayWrapperState = computed(() => {
  return (localConfig.width || 0) > 0 || (localConfig.height || 0) > 0
})

// 监听数据变化
watch(() => props.data, (data) => {
  localData.image = data.image 
  localData.key = data.key 
  localData.thumb = data.thumb 
},{deep: true})

// 暴露方法
defineExpose<ClickCaptchaExpose>({
  clear: handler.clearData,
  close: handler.close,
  refresh: handler.refresh,
  reset: handler.resetData,
  show: handler.show
})
</script>

<template>
  <div class="holly-mask" v-show="handler.isShow.show">
    <div
      :class="`holly-captcha holly-wrapper ${localConfig.showTheme && 'holly-theme'}`"
      :style="wrapperStyles"
      v-show="hasDisplayWrapperState"
    >
      <div class="holly-header">
        <span>{{ localConfig.title }}</span>
        <img v-show="hasDisplayImageState" :style="thumbStyles" :src="localData.thumb" alt="" />
      </div>
      <div class="holly-body" :style="imageStyles">
        <div class="holly-loading">
          <CaptchaLoadingIcon />
        </div>
        <img
          :style="imageStyles"
          v-show="hasDisplayImageState"
          class="holly-picture"
          :src="localData.image"
          @click="handler.clickEvent"
          alt=""
        />
        <div class="holly-dots">
          <div
            class="holly-dot"
            v-for="dot in handler.dots.list"
            :key="`${dot.key + '-' + dot.index}`"
            :style="{
              width: localConfig.dotSize + 'px',
              height: localConfig.dotSize + 'px',
              borderRadius: localConfig.dotSize + 'px',
              top: dot.y - (localConfig.dotSize || 1) / 2 - 1 + 'px',
              left: dot.x - (localConfig.dotSize || 1) / 2 - 1 + 'px'
            }"
            >{{ dot.index }}</div
          >
        </div>
      </div>
      <div class="holly-footer">
        <div class="holly-icon-block holly-icon-block2">
          <CaptchaBtnCloseIcon
            :width="localConfig.iconSize"
            :height="localConfig.iconSize"
            @click="handler.closeEvent"
          />
          <CaptchRefreshIcon
            :width="localConfig.iconSize"
            :height="localConfig.iconSize"
            @click="handler.refreshEvent"
          />
        </div>
        <div class="holly-button-block">
          <button :class="!hasDisplayImageState && 'disabled'" @click="handler.confirmEvent">{{
            localConfig.buttonText
          }}</button>
        </div>
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.holly-captcha {
  position: relative;
  top: 50%;
  left: 50%;
  background-color: #fff;
  border: 1px solid #e4e7eb;
  border-radius: 5px;
  transform: translate(-50%, -50%);
  box-shadow: 0 0 10px rgb(0 0 0 / 30%);
  box-sizing: border-box;

  .holly-icon-block2 {
    flex: 1;
  }

  .holly-dots {
    position: absolute;
    inset: 0;

    .holly-dot {
      position: absolute;
      z-index: 2;
      display: -webkit-box;
      display: flex;
      display: flexbox;
      display: flex;
      width: 22px;
      height: 22px;
      color: #cedffe;
      cursor: default;
      background: #3e7cff;
      border: 3px solid #f7f9fb;
      border-radius: 22px;
      -webkit-box-align: center;
      align-items: center;
      -ms-flex-align: center;
      justify-content: center;
    }
  }
}

.holly-mask {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 1001;
  width: 100%;
  height: 100vh;
  background: rgb(0 0 0 / 30%);

  /* display: none; */
  transition: all 0.5s;
}
</style>
